/*
	Copyright (C) 2008 by Jean-François Geyelin
	jfgeyelin@gmail.com

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the
	Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include "ObjectList.h"
#include "TriggerOnOffBlocks.h"
#include "globals.h"
#include "Plateform.h"
#include "MovingPlateform.h"
#include "Enemy.h"

ObjectList::ObjectList(void) {

	objectArray = new MyArray(64);
	objectToBeAddedArray = new MyArray(8);
	movingPlateformArray = new MyArray(8);
    //for (int i = 256; i--;) {
    for (int i = 0; i<256 ;i++) {
        objectsSortedByDepth[i] = new MyArray(4);
    }


	//Initialisation des classes qui ont des variables statics
	TriggerOnOffBlocks::setN(0);


}

ObjectList::~ObjectList(void) {

	objectArray->deleteAllObjects();
    objectToBeAddedArray->deleteAllObjects();

	delete movingPlateformArray;
	delete objectToBeAddedArray;
	delete objectArray;

    for (int i=0; i<256; i++) {
        delete objectsSortedByDepth[i];
    }

}




void ObjectList::add(Object *o) {
    objectToBeAddedArray->add(o);
}


void ObjectList::refreshPositionOfObjects(void) {
	int i,n;
	int x,x2;
	int y,y2,y3;
	MyArray **objectArrayMap = map->getObjectArrayMap();

	n = (mapWidth)*(mapHeight);
	MyArray **oam=objectArrayMap;
	for (i=0;i<n;i++) {

		if (!(*oam)->isEmpty())
		(*oam)->empty();
		oam++;
        //objectArrayMap[i]->empty();
	}

	//Object *o;
	n = objectArray->getSize();
	for (i=0;i<n;i++) {

        Object *o = objectArray->get(i);
/*
		switch (o->type) {
			case UNKNOWN:
				PRINTF("UNKNOWN");
				break;
			case MOVING_OBJECT:
				PRINTF("MOVING_OBJECT");
				break;
			case SOLID_OBJECT:
				PRINTF("SOLID_OBJECT");
				break;
			case FLOATING_OBJECT:
				PRINTF("FLOATING_OBJECT");
				break;
   			case PLATEFORM:
				PRINTF("PLATEFORM");
				break;
		}
		PRINTF("\n");
*/
		x = ((int)o->getX())+o->getCollisionX();
		y = ((int)o->getY())+o->getCollisionY();
		x2 = x+o->getCollisionWidth();
		y2 = y+o->getCollisionHeight();
		x/=16;
		y/=16;
		x2/=16;
		y2/=16;
		y3=y;
		for (;x<=x2;x++) {
			for (y=y3;y<=y2;y++) {
				if (x>=0 && x<mapWidth && y>=0 && y<mapHeight)
				objectArrayMap[x + (y)*mapWidth]->add(o);
			}
		}
	}
}





void ObjectList::draw(void) {
    for (int i = 0; i<256; i++) {
        int n = objectsSortedByDepth[i]->getSize();
        for (;n--;) {
            objectsSortedByDepth[i]->get(n)->draw();
        }
    }
}


void ObjectList::drawWithoutTheMovingObjects(void) {
    for (int i = 0; i<256; i++) {
        int n = objectsSortedByDepth[i]->getSize();
        for (;n--;) {
            if (objectsSortedByDepth[i]->get(n)->type != MOVING_OBJECT)
            objectsSortedByDepth[i]->get(n)->draw();
        }
    }
}




void ObjectList::drawForPreview(void) {
    for (int i = 0; i<256; i++) {
        int n = objectsSortedByDepth[i]->getSize();
        for (;n--;) {
            if (objectsSortedByDepth[i]->get(n) != player)
            objectsSortedByDepth[i]->get(n)->draw();
        }
    }
}


void ObjectList::animate() {


	refreshPositionOfObjects();
	int i,n;
	int i2,n2;
	int x,y,x2,y2,y3;
	MyArray **objectArrayMap = map->getObjectArrayMap();

	n = objectArray->getSize();
	MyArray arrayTemporaire(1);

    n = objectArray->getSize();


	for (i=0;i<n;i++) {
	    //PRINTF(objectArray->get(i)->getObjectType());
		objectArray->get(i)->animate();
	}


	n = objectArray->getSize();
	for (i=0;i<n;i++) {
		Object *o = objectArray->get(i);
		x = ((int)o->getX())+o->getCollisionX();
		y = ((int)o->getY())+o->getCollisionY();
		x2 = x+o->getCollisionWidth();
		y2 = y+o->getCollisionHeight();
		x/=16;
		y/=16;
		x2/=16;
		y2/=16;
		y3=y;
		arrayTemporaire.empty();
		arrayTemporaire.add(o);
		for (;x<=x2;x++) {
			for (y=y3;y<=y2;y++) {
				if (x>=0 && x<mapWidth && y>=0 && y<mapHeight) {
					MyArray *a = objectArrayMap[x + (y)*mapWidth];
					n2 = a->getSize();
				    for (i2=0;i2<n2;i2++) {
                        if (o->areColliding(a->get(i2)))
                        arrayTemporaire.carefullAdd(a->get(i2));
					}
				}
			}
		}

		n2 = arrayTemporaire.getSize();
		for (i2=1;i2<n2;i2++) {
			o->handleCollisionWithObject(arrayTemporaire.get(i2));
		}
	}


	n = objectToBeAddedArray->getSize();
	Object *o;
	for (i=0;i<n;i++) {
		o = objectToBeAddedArray->get(i);
		objectArray->add(o);

		objectsSortedByDepth[o->depth]->add(o);
		if (o->type == PLATEFORM) {
			if (((Plateform*)o)->typeOfPlateform == MOVING_PLATEFORM)
            movingPlateformArray->add(o);
		}

	}


	objectToBeAddedArray->empty();




	n = objectArray->getSize();
	for (i=0;i<n;i++) {
		o = objectArray->get(i);
		if (o->mustBeDestroyed) {
			if (o->type == PLATEFORM) {
				if (((Plateform*)o)->typeOfPlateform == MOVING_PLATEFORM)
            	movingPlateformArray->remove(o);
			}
			objectArray->remove(i);
            objectsSortedByDepth[o->depth]->remove(o);
			delete (o);
			i--;
			n--;
		}
	}


	n = movingPlateformArray->getSize();
	for (i=0;i<n;i++) {
		((MovingPlateform*)movingPlateformArray->get(i))->movePlateform();
	}


}
